package com.yc.cloud.utils;

import io.minio.MinioClient;
import io.minio.ObjectStat;
import io.minio.PutObjectOptions;
import io.minio.errors.*;
import io.minio.messages.Bucket;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.List;

/**
 * @author 杨智杰
 * @since 2021/8/26 10:27
 */
@Slf4j
@Component
public class MinIoUtil {

    /**
     * minio地址+端口号
     */
    public static String url;

    /**
     * minio用户名
     */
    public static String accessKey;

    /**
     * minio密码
     */
    public static String secretKey;

    /**
     * 默认文件桶的名称
     */
    public static String defaultBucketName;

    /**
     * minio客户端
     */
    private static MinioClient minioClient;

    /**
     * 是否连接至minio服务器
     */
    public static Boolean MINIO_IS_LINK = false;

    /**
     * 初始化minio配置
     */
    public boolean minioConfig() {
        try {
            minioClient = new MinioClient(url, accessKey, secretKey);
            createBucket(defaultBucketName);
            log.info("minio服务器连接成功!");
            MINIO_IS_LINK = true;
            return true;
        } catch (Exception e) {
            log.error("minio服务器连接失败!{}", e);
            return false;
        }
    }

    /**
     * 判断 bucket是否存在
     */
    @SneakyThrows(Exception.class)
    public static boolean bucketExists(String bucketName) {
        return minioClient.bucketExists(bucketName);
    }

    /**
     * 创建 bucket
     */
    public static void createBucket(String bucketName) throws RegionConflictException, ServerException, InvalidBucketNameException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        if (!bucketExists(bucketName)) {
            minioClient.makeBucket(bucketName);
        }
    }

    /**
     * 获取全部bucket
     */
    @SneakyThrows(Exception.class)
    public static List<Bucket> getAllBuckets() {
        return minioClient.listBuckets();
    }

    /**
     * 文件上传
     */
    @SneakyThrows(Exception.class)
    public static void upload(String bucketName, String fileName, String filePath) {
        minioClient.putObject(bucketName, fileName, filePath, null);
    }

    /**
     * 文件上传
     */
    @SneakyThrows(Exception.class)
    public static String upload(String bucketName, String fileName, InputStream stream) {
        minioClient.putObject(bucketName, fileName, stream, new PutObjectOptions(stream.available(), -1));
        return getFileUrl(bucketName, fileName);
    }

    /**
     * 文件上传
     */
    @SneakyThrows(Exception.class)
    public static String upload(String bucketName, MultipartFile file) {
        return upload(bucketName, file.getOriginalFilename(), file);
    }

    /**
     * 文件上传
     */
    @SneakyThrows(Exception.class)
    public static String upload(String bucketName, String fileName, MultipartFile file) {
        final InputStream is = file.getInputStream();
        minioClient.putObject(bucketName, fileName, is, new PutObjectOptions(is.available(), -1));
        is.close();
        return getFileUrl(bucketName, fileName);
    }

    /**
     * 删除文件
     */
    @SneakyThrows(Exception.class)
    public static void deleteFile(String bucketName, String fileName) {
        minioClient.removeObject(bucketName, fileName);
    }

    /**
     * 下载文件
     */
    @SneakyThrows(Exception.class)
    public static void download(String bucketName, String fileName, HttpServletResponse response) {
        try {
            final ObjectStat stat = minioClient.statObject(bucketName, fileName);
            response.setContentType(stat.contentType());
            response.setCharacterEncoding("UTF-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            InputStream is = minioClient.getObject(bucketName, fileName);
            IOUtils.copy(is, response.getOutputStream());
            is.close();
        } catch (Exception e) {
            response.reset();
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json;charset=UTF-8");
            PrintWriter pw = response.getWriter();
            pw.write("{\"code\":-1,\"message\":\"文件不存在!\",\"data\":null}");
            pw.flush();
            pw.close();
        }
    }

    /**
     * 获取minio文件的下载地址
     */
    @SneakyThrows(Exception.class)
    public static String getFileUrl(String bucketName, String fileName) {
        return minioClient.presignedGetObject(bucketName, fileName);
    }

}